/**
 * Copyright (c) 2011 eelpo.com
 * All rights reserved.
 */
package com.eelpo.cmmp.core.wicket.component.link;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;

import com.eelpo.common.download.FilenameUtils;

import org.apache.wicket.RequestCycle;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.request.target.resource.ResourceStreamRequestTarget;
import org.apache.wicket.util.resource.FileResourceStream;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
import org.apache.wicket.util.string.Strings;
import org.apache.wicket.util.time.Time;

/**
 * <pre>
 * 下载链接,支持所有浏览器中文显示
 * </pre>
 * 
 * @author <a href="mailto:Brian@eelpo.com">汪洪州</a>
 * @since 1.0
 */
public class CMMPDownloadLink extends Link<File> {
	private static final long serialVersionUID = -1190208934449775457L;

	private String fileName;
	private byte[] fileBytes;
	private boolean deleteAfter;

	public CMMPDownloadLink(String id, File file) {
		super(id);
		if (file == null) {
			throw new IllegalArgumentException("file cannot be null");
		}
		setDefaultModel(new Model<File>(file));
	}

	public CMMPDownloadLink(String id, IModel<File> model) {
		super(id, model);
	}

	public CMMPDownloadLink(String id, IModel<File> model, String fileName) {
		super(id, model);
		this.fileName = fileName;
	}

	public CMMPDownloadLink(String id, File file, String fileName) {
		super(id);
		if (file == null) {
			throw new IllegalArgumentException("file cannot be null");
		}
		if (Strings.isEmpty(fileName)) {
			throw new IllegalArgumentException("fileName cannot be an empty string");
		}
		setDefaultModel(new Model<File>(file));
		this.fileName = fileName;
	}

	public CMMPDownloadLink(String id, byte[] fileBytes, String fileName) {
		super(id);
		this.fileName = fileName;
		this.fileBytes = fileBytes;
	}

	@Override
	public void onClick() {

		if (fileBytes == null || fileBytes.length == 0) {
			final File file = getModelObject();

			if (file == null) {
				throw new IllegalStateException(getClass().getName() + " failed to retrieve a File object from model");
			}
			String agent = ((WebRequest) getRequest()).getHttpServletRequest().getHeader("USER-AGENT");

			final String fn = FilenameUtils.encode(agent, fileName != null ? fileName : file.getName());

			IResourceStream resourceStream = new FileResourceStream(new org.apache.wicket.util.file.File(file));
			getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream) {
				@Override
				public String getFileName() {
					return fn;
				}

				@Override
				public void respond(RequestCycle requestCycle) {
					super.respond(requestCycle);

					if (deleteAfter)
						file.delete();
				}
			});
		} else {
			String agent = ((WebRequest) getRequest()).getHttpServletRequest().getHeader("USER-AGENT");

			final String fn = FilenameUtils.encode(agent, fileName);

			IResourceStream resourceStream = new ByteResourceStream(fileBytes);
			getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream) {
				@Override
				public String getFileName() {
					return fn;
				}
			});
		}
	}

	public final CMMPDownloadLink setDeleteAfterDownload(boolean deleteAfter) {
		this.deleteAfter = deleteAfter;
		return this;
	}
}

class ByteResourceStream implements IResourceStream {

	private static final long serialVersionUID = -9209808810242631739L;

	private byte[] array;
	private transient InputStream inputStream;

	public ByteResourceStream(byte[] bytes) {
		this.array = bytes;
	}

	@Override
	public void close() throws IOException {
		if (inputStream != null) {
			inputStream.close();
			inputStream = null;
		}
	}

	@Override
	public String getContentType() {
		return null;
	}

	@Override
	public InputStream getInputStream() throws ResourceStreamNotFoundException {
		if (inputStream == null) {
			inputStream = new ByteArrayInputStream(array);
		}

		return inputStream;
	}

	@Override
	public Locale getLocale() {
		return Locale.getDefault();
	}

	@Override
	public long length() {
		return array.length;
	}

	@Override
	public void setLocale(Locale locale) {

	}

	@Override
	public Time lastModifiedTime() {
		return null;
	}
}
